/**
 * Module dependencies
 */

var util = require('util');
var _ = require('lodash');
_.defaults = require('merge-defaults');
var fs = require('fs');
var path = require('path');
_.str = require('underscore.string');

var templateMap = require('./templates');
var modelParser = require('./modelParser');
var compiler = require('./tplCompiler');

var formBuilder = require('./formBuilder');
/**
 * sails-generate-page
 *
 * Usage:
 * `sails generate page`
 *
 * @description Generates a page
 * @help See http://links.sailsjs.org/docs/generators
 */

module.exports = {

  /**
   * `before()` is run before executing any of the `targets`
   * defined below.
   *
   * This is where we can validate user input, configure default
   * scope variables, get extra dependencies, and so on.
   *
   * @param  {Object} scope
   * @param  {Function} cb    [callback]
   */

  before: function (scope, cb) {

    // scope.args are the raw command line arguments.
    //
    // e.g. if someone runs:
    // $ sails generate page user find create update
    // then `scope.args` would be `['user', 'find', 'create', 'update']`
    if (!scope.args[0]) {
      return cb(new Error('请指定model文件.'));
    }

    // scope.rootPath is the base path for this generator
    //
    // e.g. if this generator specified the target:
    // './Foobar.md': { copy: 'Foobar.md' }
    //
    // And someone ran this generator from `/Users/dbowie/sailsStuff`,
    // then `/Users/dbowie/sailsStuff/Foobar.md` would be created.
    if (!scope.rootPath) {
      return cb(INVALID_SCOPE_VARIABLE('rootPath'));
    }


    // Attach defaults
    _.defaults(scope, {
      createdAt: new Date()
    });

    var upperFirst = function (letter) {
      return letter.replace(/(\w)/, function (v) {
        return v.toUpperCase()
      });
    };

    var arr2str = function (arr) {
      var str = '[';
      for (var i in arr) {
        var v = arr[i];
        if (i != 0) {
          str += ',';
        }
        str += '\'' + v + '\'';
      }
      return str + ']';
    };

    // Decide the output filename for use in targets below:
    var inputName = scope.args[0];
    var clazz = upperFirst(inputName);
    var fileName = clazz;
    var objName = inputName.replace(/(\w)/, function (v) {
      return v.toLowerCase()
    });
    //if(scope.coffee) {
    fileName += '.coffee';
    //}else{
    //  fileName += '.js';
    //  return cb(new Error('暂不支持js格式的model文件.'));
    //}
    scope.filename = fileName;

    // Add other stuff to the scope for use in our templates:
    scope.whatIsThis = 'an example file created at ' + scope.createdAt;

    var model = modelParser(fileName);
    var page = model.page;

    if(page.generated) {
      return cb(new Error('this model has been generated already.'));
    }

    var global = _.defaults({
      title: page.title,
      obj: page.obj || objName,//首字母小写
      clazz: clazz,//首字母大写

      //fun
      fn_upper_first: upperFirst,
      arr2str: arr2str,
    }, model);

    global['formBuilder'] = new formBuilder(global);

    //this.targets = {
    //  page: './views/' + global.obj + '.ejs',
    //  ctrl: './assets/js/admin/' + global.obj + 'Ctrl.js',
    //};
    this.targets['./views/admin/' + global.obj + '.ejs'] = {template: {templatePath: 'page.template', force: true}};
    this.targets['./assets/js/admin/' + global.obj + 'Ctrl.js'] = {
      template: {
        templatePath: 'pageCtrl.js.template',
        force: true
      }
    };

    _.defaults(scope, global, {
      // search from
      compiledSearchForm: compiler.compile('searchForm', global),
      // table 相关
      compiledTableThread: compiler.compile('tableThread', global),
      compiledTableBody: compiler.compile('tableBody', global),

      // edit form
      compiledEditForm: compiler.compile('editForm', global),

      // main page
      compiledHomePageEJS: templateMap.homePage()

      // angular ctrl
    });

    // When finished, we trigger a callback with no error
    // to begin generating files/folders as specified by
    // the `targets` below.
    cb();
  },


  /**
   * The files/folders to generate.
   * @type {Object}
   */

  targets: {

    // Usage:
    // './path/to/destination.foo': { someHelper: opts }

    // Creates a dynamically-named file relative to `scope.rootPath`
    // (defined by the `filename` scope variable).
    //
    // The `template` helper reads the specified template, making the
    // entire scope available to it (uses underscore/JST/ejs syntax).
    // Then the file is copied into the specified destination (on the left).

    //'./views/generated.ejs': {template: {templatePath: 'homePage.template', force: true}},
    //'./views/generated.ejs': {template: {templatePath: 'page.template', force: true}},
    //'./views/pageCtrl.js': {template: {templatePath: 'pageCtrl.js.template', force: true}},

    // Creates a folder at a static path
    //'./hey_look_a_folder': { folder: {} }

  },


  /**
   * The absolute path to the `templates` for this generator
   * (for use with the `template` helper)
   *
   * @type {String}
   */
  templatesDirectory: require('path').resolve(__dirname, './templates')
};


/**
 * INVALID_SCOPE_VARIABLE()
 *
 * Helper method to put together a nice error about a missing or invalid
 * scope variable. We should always validate any required scope variables
 * to avoid inadvertently smashing someone's filesystem.
 *
 * @param {String} varname [the name of the missing/invalid scope variable]
 * @param {String} details [optional - additional details to display on the console]
 * @param {String} message [optional - override for the default message]
 * @return {Error}
 * @api private
 */

function INVALID_SCOPE_VARIABLE(varname, details, message) {
  var DEFAULT_MESSAGE =
    'Issue encountered in generator "page":\n' +
    'Missing required scope variable: `%s`"\n' +
    'If you are the author of `sails-generate-page`, please resolve this ' +
    'issue and publish a new patch release.';

  message = (message || DEFAULT_MESSAGE) + (details ? '\n' + details : '');
  message = util.inspect(message, varname);

  return new Error(message);
}
